package com.zx.ms.test.springcloud.hystrixconsumer.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.annotation.ObservableExecutionMode;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import com.netflix.hystrix.contrib.javanica.command.AsyncResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Subscriber;

import java.util.List;
import java.util.concurrent.Future;

import static com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL;

@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * Setter 分组
     * @param id
     * @return
     */
    @CacheResult
    //清除缓存
    //@CacheRemove(commandKey = "getUserById")
    @HystrixCommand(commandKey = "getUserById",groupKey ="UserGroup",threadPoolKey = "getUserByIdThread")
    public String getUserById(Long id){
        return restTemplate.getForObject("http://HELLO-DEV/hello",String.class,id);
    }

    /**
     * ignoreExceptions 忽略某异常不进行fallback处理
     * @param id
     * @return
     */
    //@CacheResult(cacheKeyMethod = "getCacheKey")
    @CacheResult
    @HystrixCommand(fallbackMethod = "error" ,defaultFallback = "defaultError",ignoreExceptions = {Exception.class})
    public Future<String> getUserByIdAsync(@CacheKey("id")final Long id){

       return new AsyncResult<String>() {
           @Override
           public String invoke() {
               return restTemplate.getForObject("http://HELLO-DEV/hello",String.class,id);
           }

           @Override
           public String get() {
               return invoke();
           }
       };
    }
    //observable模式
    @HystrixCommand(observableExecutionMode = ObservableExecutionMode.EAGER)
    public Observable<String> getUserByIdAsync1(final String id){

        return Observable.create(new Observable.OnSubscribe<String>(){

            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if(!subscriber.isUnsubscribed()){
                        String s = restTemplate.getForObject("http://HELLO-DEV/hello",String.class,id);
                        subscriber.onNext(s);
                        subscriber.onCompleted();
                    }
                } catch (Exception e){
                    subscriber.onError(e);
                }
            }
        });
    }

    //toObservable 模式
    @HystrixCommand(observableExecutionMode = ObservableExecutionMode.LAZY)
    public Observable<String> getUserByIdAsync2(final String id){

        return Observable.create(new Observable.OnSubscribe<String>(){

            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if(!subscriber.isUnsubscribed()){
                        String s = restTemplate.getForObject("http://HELLO-DEV/hello",String.class,id);
                        subscriber.onNext(s);
                        subscriber.onCompleted();
                    }
                } catch (Exception e){
                    subscriber.onError(e);
                }
            }
        });
    }

    @HystrixCommand(fallbackMethod = "defaultError")
    public String error(String id,Throwable e){
        System.out.println(e.getMessage());
        return "u a error";
    }

    public String defaultError(String id,Throwable e){
        System.out.println(e.getMessage());
        return " error default";
    }


    /**
     * 缓存处理
     * @param id
     * @return
     */
    protected String getCacheKey(Long id) {
        return String.valueOf(id);
    }


    /**
     * 合并处理
     * @param id
     * @return
     */
    @HystrixCollapser(batchMethod = "findAll" ,scope = GLOBAL
            , collapserProperties = {@HystrixProperty(name= "timerDelayInMilliseconds" ,value ="100")})
    public String find(String id){
        System.out.println(id);
        return null;
    }

    @HystrixCommand
    public List<String> findAll(List<String> ids){
        List l = restTemplate.getForObject("http://HELLO-DEV/helloAll",List.class, StringUtils.join(ids,","));
        System.out.println(l);
        return l;
    }

}
